﻿using _26._1_访问修饰符_被调用程序集;
using System;

namespace _26___面向对象_访问修饰符
{
    class Program
    {
        static void Main(string[] args)
        {
            // public 访问修饰符的跨类类型使用
            var p1 = new Person("张三");
            var str = p1.name;
            // private 访问修饰符的外部访问 - NG
            //var mm = p1.秘密;
            // public 访问修饰符的跨程序集的访问
            Dog dog = new Dog("大白");
            Console.WriteLine($"狗狗的名字 = {dog.name}");

            //protected 访问修饰符的外部访问 - NG
            Student student = new Student("小小");
            //var zcmm = student.祖传秘密;

            // internal 访问修饰符的同一个程序集的外部访问 
            var mw = p1.村中密闻;
            var p2 = new Person("张三");
            var mw2 = p2.村中密闻;
            var ck = p2.存款;


        }
        // 访问修饰符
        //1. public : 公开的，可跨类类型访问，可跨程序集访问 ，访问啥：类类型，类中的成员
        //2. private ：私有的，只能在当前类型中访问（class 、struct），命名空间中不能用private （只能用 public 、internal）
        //2.1 private 访问啥：类中的成员 
        //3. protected: 保护的（家族式的行为）， 在当前类型中访问、在继承类中访问 ,修饰类型成员
        //3.1 protected 在类中类可以用在 类类型
        //4. internal ：内部的， 只能在同一个程序集访问，不可跨程序集访问 ，修饰的是类类型、类中的成员

        //5. protected internal : 不能在命名空间中对类类型进行修饰 ，类中类 OK
        //5.1 internal (村的保护级别) protected （家族的保护级别），
        //5.2 他俩结合是啥意思：不能跨程序集，能够在继承类中访问，能够在继承类之外访问。
    }

    // 在这里，村 = 程序集
    // ox: 牛，牛只能在村里，不能出村，要保护，不然来年春耕没得搞了
    internal class OX { }

    // 跨类类型使用
    public class Person
    {
        public string name;
        private string 秘密;
        protected string 祖传秘密;
        internal string 村中密闻;
        protected internal int 存款;
        public Person(string v)
        {
            this.name = v;
        }
        // private 等不能在命名空间中对类类型进行修饰的访问修饰符，但是类中类 可以随便玩
        private class Mouth { }
        protected class Mouth3 { }
        protected internal class Mouth2 { }
        private enum Drinks { }
    }

    public class Student : Person
    {
        public Student(string name) : base(name) { }
        public void 问妈妈秘密是什么()
        {
            // Internal 访问修饰符的 继承类中的访问 - OK
            Console.WriteLine(this.祖传秘密);
            // private 访问修饰符的继承类中的访问 - NG  （每个人都会有秘密，你的祖辈也一样）
            // Console.WriteLine(this.秘密);
            var ck = this.存款;
        }
    }

    internal class InternalA
    {
        public string name;
    }

    //访问修饰符的其他注意事项：
    /*
     * 1. Interface ：抽象成员不能有访问修饰符，方法一旦有访问修饰符就必须实现
     * 2. 枚举的成员不能有访问修饰符,有则导致IDE紊乱
     * 3. 枚举本身在命名空间中不能用 private 等，和 class 规则保持一致。
     * 4. 委托、事件可以当成类类型的声明，所以修饰符的使用规则符合 class 和 enum 上用的规则
     */
    
    // 默认是 internal
    enum Drinks
    {
        白开水,
    }

    // 委托的访问修饰符
    // 默认是 internal , internal :内部的
    delegate void SomeEvent();
    public delegate void SomeEvent2();

}
